home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / comm / clink120.zip / SEALINK.C < prev    next >
C/C++ Source or Header  |  1987-08-24  |  23KB  |  608 lines

  1. /*  SEAlink - Sliding window file transfer protocol
  2.  
  3.     Version 1.20, created on 08/05/87 at 17:51:40
  4.  
  5.     Copyright 1986,87 by System Enhancement Associates; ALL RIGHTS RESERVED
  6.  
  7.     By:  Thom Henderson
  8.  
  9.     Description:
  10.  
  11.          This file contains a set of routines to illustrate the SEAlink
  12.          sliding window file transfer protocol.  SEAlink is fully backward
  13.          compatible to XMODEM, and can be easily adapted to most XMODEM
  14.          variants.
  15.  
  16.          The intent of SEAlink is to provide a file transfer protocol that
  17.          does not suffer from propagation delays, such as are introduced
  18.          by satellite relays or packet switched networks.
  19.  
  20.     Instructions:
  21.  
  22.          Two routines are provided to implement SEAlink file transfers.
  23.  
  24.          int xmtfile(name)             /+ transmit a file +/
  25.          char *name;                   /+ name of file to transmit +/
  26.  
  27.          This routine is used to send a file.  One file is sent at a time.
  28.          If the name is blank (name is null or *name points to a null),
  29.          then only an end of transmission marker is sent.
  30.  
  31.          This routine returns a one if the file is successfully
  32.          transmitted, or a zero if a fatal error occurs.
  33.  
  34.          char *rcvfile(name)           /+ receive a file +/
  35.          char *name;                   /+ name of file (optional) +/
  36.  
  37.          This routine is used to receive a file.  One file is received.
  38.          The name, if given, takes precedence and will be the name of
  39.          the resulting file.  If the name is blank (name is null or *name
  40.          points to a null), then the name given by the transmitter is used.
  41.          If the transmitter does not give a name, then the file transfer
  42.          is aborted.
  43.  
  44.          This routine returns a pointer to the name of the file that
  45.          was received.  If the file transfer is not successful, then
  46.          a null pointer is returned.
  47.  
  48.          The pointer returned by rcvfile() points to a static data buffer.
  49.          This does not have to be freed (and should not be), but it will
  50.          be overwritten the next time rcvfile() is called.
  51.  
  52.          The rcvfile() function works on a temporary file whose name is
  53.          the same as the final file, but with a dash ("-") added at the
  54.          beginning.  If a file transfer is aborted, then this temporary
  55.          file will be retained.  An aborted file transfer will not harm
  56.          a pre-existing file of the same name.
  57.  
  58.     Programming notes:
  59.  
  60.          These routines can be used for either single or multiple file
  61.          transfers.
  62.  
  63.          To send multiple files, send each one one at a time until either
  64.          a transmit fails or all files are sent.  If all files are sent,
  65.          then signal the end by calling xmtfile() with a null pointer.
  66.  
  67.          To receive multiple files, call rcvfile() repeatedly until it
  68.          returns a null pointer.
  69.  
  70.          These routines pass a "block zero", which contains information
  71.          about the original file name, size, and date/time of last
  72.          modification.  If you cannot implement block zero, then you can
  73.          leave it out.  If you cannot set any given field in block zero
  74.          when transmitting, then you should leave it set to zeros.  If you
  75.          cannot use any given field of block zero when receiving, then
  76.          you should ignore it.
  77.  
  78.          These routines are fully compatible with XMODEM, including the
  79.          original checksum method and later CRC adaptations.  It can be
  80.          easily adapted to Modem7 protocol by adding a Modem7 filename
  81.          transfer shell, though we do not recommend it.  The underlying
  82.          logic, of course, can be adapted to almost any variant of XMODEM.
  83.  
  84.     License:
  85.  
  86.          You are granted a license to use this code in your programs, and
  87.          to adapt it to your particular situation and needs, subject only
  88.          to the following conditions:
  89.  
  90.          1)   You must refer to it as the SEAlink protocol, and you must
  91.               give credit to System Enhancement Associates.
  92.  
  93.          2)   If you modify it in such a way that your version cannot
  94.               converse with the original code as supplied by us, then
  95.               you should refer to it as "SEAlink derived", or as a
  96.               "variation of SEAlink", or words to that effect.
  97.  
  98.          In short, we're not asking for any money, but we'd like to
  99.          get some credit for our work.
  100.  
  101.     Language:
  102.          Computer Innovations Optimizing C86
  103. */
  104. #include <stdio.h>
  105. #include "fstat.h"
  106. #include <time.h>
  107.  
  108. struct zeros                           /* block zero data structure */
  109. {   long flen;                         /* file length */
  110.     long fstamp;                       /* file date/time stamp */
  111.     char fnam[17];                     /* original file name */
  112.     char prog[15];                     /* sending program name */
  113.     char noacks;                       /* true if ACKing not required */
  114.     char fill[87];                     /* reserved for future use */
  115. }   ;
  116.  
  117. #define ACK 0x06
  118. #define NAK 0x15
  119. #define SOH 0x01
  120. #define EOT 0x04
  121.  
  122. #define WINDOW 6                       /* normal window size */
  123.  
  124. static int outblk;                     /* number of next block to send */
  125. static int ackblk;                     /* number of last block ACKed */
  126. static int blksnt;                     /* number of last block sent */
  127. static int slide;                      /* true if sliding window */
  128. static int ackst;                      /* ACK/NAK state */
  129. static int numnak;                     /* number of sequential NAKs */
  130. static int chktec;                     /* check type, 1=CRC, 0=checksum */
  131. static int toterr;                     /* total number of errors */
  132. static int ackrep;                     /* true when ACK or NAK reported */
  133. static int ackseen;                    /* count of sliding ACKs seen */
  134.  
  135. char *progname = "Your name here";     /* name of sending program */
  136. int ackless = 0;                       /* true if ACKs not required */
  137.  
  138. /*  File transmitter logic */
  139.  
  140. int xmtfile(name)                      /* transmit a file */
  141. char *name;                            /* name of file to send */
  142. {
  143.     FILE *f, *fopen();                 /* file to send */
  144.     long t1, timerset();               /* timers */
  145.     int endblk;                        /* block number of EOT */
  146.     struct filstat fst;                /* data about file */
  147.     struct zeros zero;                 /* block zero data */
  148.  
  149.     if(name && *name)                  /* if sending a file */
  150.     {    if(!(f=fopen(name,"rb")))
  151.          {    printf("  Can't read %s\n",name);
  152.               return 0;
  153.          }
  154.  
  155.          setmem(&zero,sizeof(zero),0); /* clear out data block */
  156.  
  157.          filestat(name,&fst);          /* get file statistics */
  158.          zero.flen = fst.fs_fsize;
  159.          zero.fstamp = fst.fs_abs;
  160.          strcpy(zero.fnam,fst.fs_fname);
  161.          strcpy(zero.prog,progname);
  162.          zero.noacks = ackless;
  163.  
  164.          endblk = ((zero.flen+127)/128) + 1;
  165.          printf("  Ready to send %d blocks of %s\n",endblk-1,zero.fnam);
  166.     }
  167.     else endblk = 0;                   /* fake for no file */
  168.  
  169.     outblk = 1;                        /* set starting state */
  170.     ackblk = -1;
  171.     blksnt = slide = ackst = numnak = toterr = ackrep = ackseen = 0;
  172.     chktec = 2;                        /* undetermined */
  173.  
  174.     t1 = timerset(300);                /* time limit for first block */
  175.     printf("  Waiting...\r");
  176.  
  177.     while(ackblk<endblk)               /* while not all there yet */
  178.     {    if(!carrier())
  179.          {    printf("\n  Lost carrier\n");
  180.               goto abort;
  181.          }
  182.          if(key_scan()!=EOF)
  183.          {    if((key_getc()&0xff)==27)
  184.               {    printf("\n  Aborted by operator\n");
  185.                    goto abort;
  186.               }
  187.          }
  188.          if(timeup(t1))
  189.          {    printf("\n  Fatal timeout\n");
  190.               goto abort;
  191.          }
  192.  
  193.          if(outblk <= ackblk + (slide? WINDOW : 1))
  194.          {    if(out